import React, { useState, useEffect, useRef } from 'react'
import style from './Index.module.less'
import { Form, Row, Col, Input, message } from 'antd'
import { componentMap, formatComponentSubmitValue, formatComponentInitValue } from './components/map'
import { formatValidateRules } from './tool'
import Text from '@components/Text'
import { useSelector, useDispatch } from 'react-redux'
import OperateBtns from './components/OperateBtns/Index'
import { ExclamationCircleOutlined } from '@ant-design/icons'
import { $post } from '@js/authRequest'
import NextOperatorSelector from './components/NextOperatorSelector/Index'
import { awaitWrap } from '@src/assets/js/tool'
import { updateUncompleteMessage } from '@redux/actions'

const { Item } = Form

// 点击按钮，触发操作
function doAction (instance, formRef, setLoading, setAction, setFormData, setNextOperatorSelectorVisible, refreshApprove, action, dispatch) {
  setAction(action)
  const c = formRef.current
  if (['disagree', 'cancel'].indexOf(action.opt_add) !== -1) {
    dealAction(instance, action, { remark: c.getFieldValue(['remark']) }, setLoading, setFormData, setAction, setNextOperatorSelectorVisible, refreshApprove, dispatch)
  } else {
    c.submit()
  }
}

// 进行操作
async function dealAction (instance, action, formData, setLoading, setFormData, setAction, setNextOperatorSelectorVisible, refreshApprove, dispatch) {
  setFormData(formData)
  if (!action.next_operators || action.next_operator_type !== 'step_some') { // 当下一步没有操作者时，直接提交
    return toSubmitAction(instance, action, dispatch, formData, setLoading, setAction, refreshApprove)
  }
  if (action.next_operators.length === 1) {
    toSubmitAction(instance, action, dispatch, formData, setLoading, setAction, refreshApprove, action.next_operators[0].id)
  } else {
    setNextOperatorSelectorVisible(true)
  }
}

// 从当前操作步骤中获取vars
async function getVarsFromFormData (instance, action, formData) {
  const vars = instance.currentStep.vars.map(li => ({ key: li.key, title: li.title, type: li.type, value: li.value }))
  if (['disagree', 'cancel'].indexOf(action.opt_add) !== -1) {
    return []
  }
  vars.forEach(v => {
    // delete v.type
    v.value = (formData.vars || {})[v.key] || ''
  })
  for (let i = 0; i < vars.length; i++) {
    vars[i].value = await formatComponentSubmitValue(vars[i])
  }
  return vars
}

// 提交操作请求
async function toSubmitAction (instance, action, dispatch, formData, setLoading, setAction, refreshApprove, nextOperatorId, forcepassage) {
  setLoading(true)
  const hide = message.loading('提交中', 120)
  const [err, vars] = await awaitWrap(getVarsFromFormData(instance, action, formData))
  if (err) {
    hide()
    setLoading(false)
    return message.warning(err.message)
  }
  const data = {
    flowid: instance.flowid,
    flow_instanceid: instance.id,
    actionid: action.id,
    action_name: action.name,
    stepid: instance.currentStep.stepid,
    remark: formData.remark,
    operatorid_to: nextOperatorId,
    vars
  }
  if (Object.prototype.hasOwnProperty.call(action, 'level')) {
    data.level = action.level
  }
  if (forcepassage) {
    data.forcepassage = 1
  }
  $post('/api/vendor/flowinstance/action', data).then(res => {
    setLoading(false)
    hide()
    if (res.status === 1) {
      setAction(null)
      refreshApprove()
      dispatch(updateUncompleteMessage(dispatch))
    } else if (res.status === 2) {
      requestAgainConfirm(res.message, () => toSubmitAction(instance, action, dispatch, formData, setAction, refreshApprove, nextOperatorId, true))
    } else {
      message.warning(res.message)
    }
  }).catch(() => {
    hide()
    setLoading(false)
  })
}

// 格式化表单初始化数据
function formatFormData (data) {
  if (!data) {
    return {}
  }
  const vars = (data.vars || [])
  const formData = { vars: {} }
  vars.forEach(li => {
    if (li.value) {
      formData.vars[li.key] = formatComponentInitValue(li)
    }
  })
  return formData
}

//  强制重新请求提示
function requestAgainConfirm (content, onOk) {
  confirm({
    icon: <ExclamationCircleOutlined />,
    content,
    onOk,
    okText: '强制提交'
  })
}

function getOtherVars (list) {
  return list.filter(li => {
    if (li.type === '文书') {
      return false
    }
    if (li.typeconfig && li.typeconfig.historyOnly) {
      return false
    }
    return true
  })
}

function Main ({ data, instance, refreshApprove }) {
  const formRef = useRef(null)
  const [firstLabelCol, setFirstLabelCol] = useState(80)
  const [action, setAction] = useState(null)
  const [docVars, setDocVars] = useState([])
  const [otherVars, setOtherVars] = useState([])
  const [formData, setFormData] = useState({})
  const [nextOperatorSelectorVisible, setNextOperatorSelectorVisible] = useState(false)
  const [loading, setLoading] = useState(false)
  const [formInitData, setFormInitData] = useState(null)
  const dispatch = useDispatch()
  const { realname } = useSelector(state => {
    return {
      realname: state.basic.userInfo.realname
    }
  })
  useEffect(() => {
    const vars = data.vars || []
    if (vars[0]) {
      setFirstLabelCol(vars[0].labelcol || 80)
    }
    setDocVars(vars.filter(li => li.type === '文书'))
    setOtherVars(getOtherVars(vars))
    setFormInitData(formatFormData(data))
  }, [data])
  useEffect(() => {
    const c = formRef.current
    if (c && formInitData) {
      c.setFieldsValue(formInitData)
    }
  }, [formRef, formInitData])
  return (
    <div className={style.contaienr}>
      <NextOperatorSelector visible={nextOperatorSelectorVisible} list={(action && action.next_operators) || []} hide={() => setNextOperatorSelectorVisible(false)} changeOperatorId={v => toSubmitAction(instance, action, dispatch, formData, refreshApprove, v)} />
      <div className={style['title-line']}>{data.step_name}</div>
      <Form name={data.id} ref={formRef} initialValues={formInitData || {}} onFinish={d => dealAction(instance, action, d, setLoading, setFormData, setAction, setNextOperatorSelectorVisible, refreshApprove, dispatch)}>
        <div className={style['form-vars']}>
          <Row gutter={24}>
            <Col span={8}>
              <Item label='操作者' labelCol={{ flex: `${firstLabelCol}px` }} style={{ marginBottom: '8px' }}>
                <Text value={realname} />
              </Item>
            </Col>
          </Row>
          <Row gutter={24}>
            {otherVars.map((li, i) => { // 渲染除文书外的其他vars
              const Component = componentMap[li.type]
              const rules = formatValidateRules(li.validation_rule)
              if (li.typeconfig && li.typeconfig.historyOnly) {
                return <span key={i} />
              }
              if (li.type === '回调按钮') {
                return (
                  <Col span={li.span || 8} key={li.key}>
                    {Component ? <Component title={li.title} config={li.typeconfig} /> : <div />}
                  </Col>
                )
              }
              return (
                <Col span={li.span || 8} key={li.key}>
                  <Item name={['vars', li.key]} label={li.title} rules={rules} labelCol={{ flex: `${li.labelcol || 80}px` }}>
                    {Component ? <Component options={li.options} config={li.typeconfig} /> : <div />}
                  </Item>
                </Col>
              )
            })}
          </Row>
        </div>
        {
          // 渲染文书
          docVars.map((li) => (
            <Item key={li.key} noStyle name={['vars', li.key]}>
              <span />
            </Item>
          ))
        }
        <div className={style['operate-block']}>
          <Row gutter={24}>
            <Col span={12}>
              <Item label={data.remark_alias || '备注'} name='remark' style={{ marginBottom: 0 }}>
                <Input placeholder='请输入备注' className={style.full} />
              </Item>
            </Col>
            <Col span={12} className={style['operate-btns']}>
              {data && <OperateBtns data={data} instance={instance} loading={loading} refreshApprove={refreshApprove} action={action} setAction={setAction} formRef={formRef} callBack={d => doAction(instance, formRef, setLoading, setAction, setFormData, setNextOperatorSelectorVisible, refreshApprove, d, dispatch)} />}
            </Col>
          </Row>
        </div>
      </Form>
    </div>
  )
}

export default Main
